//
//  PolynLiveVideoView.m
//  Pods
//
//  Created by Jared on 2019/10/29.
//

#import "LiveVideoView.h"
#import <IJKMediaFramework/IJKMediaFramework.h>
//#import "PLVLivePlayerControllerSkin.h"
#import <PLVLiveAPI/PLVLiveConfig.h>
#import <PLVLiveAPI/PLVLiveAPI.h>
#import "PLVLivePlayerController.h"
#import "ZJZDanMu.h"
#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>

#import "PLVLiveManager.h"
#import "PLVUtils.h"
#import <MBProgressHUD/MBProgressHUD.h>

#ifdef DEBUG
#   define DLog(fmt, ...) NSLog((@"%s [Line %d] [Native打印]" fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#   define DLog(...)
#endif

@interface LiveVideoView()
@property (strong, nonatomic) UISlider *volumeSliderPlug;
@end

@implementation LiveVideoView{
    //IOSTextView 创建后的标识
    int64_t _viewId;
    //消息回调
    FlutterMethodChannel * _channel;
    UIView * _displayView;                  // 播放器显示层
    
    PLVLivePlayerController * _livePlayer;
//    PLVLivePlayerControllerSkin * _playerSkin;
    
    PLVLiveChannel *_liveChannel;           //直播频道model
    NSString *_stream;
    
    // 初始化测试信息
    NSString * _userId;                     //观看用户id
    NSUInteger _channelId;                  // 直播频道 Id
    ZJZDanMu *_danmuLayer;                  // 弹幕层
    BOOL _danmuEnable;                      // 是否开启弹幕
//    UISlider * _volumeSliderPlug;                //音量
    NSString * _appId;
    NSString * _appSecret;
    
    NSString *_nickName;                    // 聊天室用户昵称
    NSString *_avatar;                      // 聊天室用户头像
    PLVSocketIO *_socketIO;
    PLVSocketObject *_login;                // Socket 登录对象
    BOOL _loginSuccess;                     // Socket 登录成功
//    FTPageController *pageController;       // 页控制器
    PLVChatroomController *_chatroomController;    // 互动聊天室(房间内公共聊天)
    PLVOnlineListController *_onlineListController;// 在线列表控制器
    PLVChatroomController *_privateChatController; // 咨询提问聊天室(房间内私有聊天)
}


//在这里只是创建了一个UILabel
- (instancetype)initWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id)args binaryMessenger:(NSObject<FlutterBinaryMessenger> *)messenger{

    if (self = [super init]) {
        _viewId = viewId;
        
        // 注册flutter 与 ios 通信通道
        NSString* channelName = [NSString stringWithFormat:@"polyv_live_video_plugin_%lld", viewId];
        _channel = [FlutterMethodChannel methodChannelWithName:channelName binaryMessenger:messenger];
        
//        NSString *appId = @"endz3vf26q";
        NSString * appId = @"appId";
        if ([args isKindOfClass:[NSDictionary class]]) {
                NSDictionary *params = (NSDictionary *)args;
                [[params allKeys] containsObject:appId] ? [[params valueForKey:appId] isKindOfClass:[NSString class]] ? _appId = [params valueForKey:appId] : nil : nil;
        }
//        NSString *appSecret = @"ba95e2f2fd394ff19a1cd1b248839102";
        NSString * appSecret = @"appSecret";
        if ([args isKindOfClass:[NSDictionary class]]) {
                NSDictionary *params = (NSDictionary *)args;
                [[params allKeys] containsObject:appSecret] ? [[params valueForKey:appSecret] isKindOfClass:[NSString class]] ? _appSecret = [params valueForKey:appSecret] : nil : nil;
        }
        
//        _appId = @"endz3vf26q"; _appSecret = @"ba95e2f2fd394ff19a1cd1b248839102";
////        DLog(@"appId = %@ \n appSecret = %@",appId,appSecret);
////        if ([appId isEqualToString:@"appId"]) return nil;
//        _appId = appId; _appSecret = appSecret;
//        [PLVLiveConfig liveConfigWithAppId:appId appSecret:appSecret];
        
//        _userId = @"e77rl86axa";
//        NSString * userId = @"userId";
//        if ([args isKindOfClass:[NSDictionary class]]) {
//                NSDictionary *params = (NSDictionary *)args;
//                [[params allKeys] containsObject:userId] ? [[params valueForKey:userId] isKindOfClass:[NSString class]] ? _userId = [params valueForKey:userId] : nil : nil;
//        }
////        _channelId = 373238;
////        _channelId = 127889;
//        NSString * channelId = @"channelId";
//        if ([args isKindOfClass:[NSDictionary class]]) {
//                NSDictionary *params = (NSDictionary *)args;
//                [[params allKeys] containsObject:channelId] ? [[params valueForKey:channelId] isKindOfClass:[NSString class]] ? channelId = [params valueForKey:channelId] : nil : nil;
//        }
//        _channelId = [channelId integerValue];
//        if ([_userId isEqualToString:@""] || _channelId > 0) return nil;
//
//        [self isRegistedPLVLive];
        
//        if (frame.size.width == 0) {
//            frame = CGRectMake(frame.origin.x, frame.origin.y, [UIScreen mainScreen].bounds.size.width, 212);
//        }
        _displayView = [[UIView alloc] initWithFrame:frame];
        _displayView.backgroundColor = [UIColor blackColor];
        
        MPVolumeView *volumeView = [MPVolumeView new];
        volumeView.frame = CGRectMake(-1000, -1000, 100, 100);
        volumeView.hidden = NO;
        for (UIView *view in [volumeView subviews]){
            if ([view.class.description isEqualToString:@"MPVolumeSlider"]){
                self.volumeSliderPlug = (UISlider*)view;
                break;
            }
        }
        [_displayView addSubview:volumeView];
        
        [self addNotifications];

        __weak __typeof__(self) weakSelf = self;
        [_channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
          [weakSelf handleMethodCall:call result:result];
        }];
    }
    return self;
}

- (void)addNotifications{
    // 注册播放器通知
//    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(livePlayerPlaystateCallback) name:IJKMPMediaPlaybackIsPreparedToPlayDidChangeNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(livePlayerReconnectNotification:) name:PLVLivePlayerReconnectNotification object:nil];
//    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(livePlayerWillChangeToFullScreenNotification) name:PLVLivePlayerWillChangeToFullScreenNotification object:nil];
//    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(livePlayerWillExitFullScreenNotification) name:PLVLivePlayerWillExitFullScreenNotification object:nil];
//     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayerPlaybackStateDidChange:) name:IJKMPMoviePlayerPlaybackStateDidChangeNotification object:self];
}

//- (void)configObservers {
//    NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
//    [defaultCenter addObserver:self selector:@selector(movieNaturalSizeAvailable:) name:IJKMPMovieNaturalSizeAvailableNotification object:self];
//
//    [defaultCenter addObserver:self selector:@selector(mediaPlaybackIsPreparedToPlay:) name:IJKMPMediaPlaybackIsPreparedToPlayDidChangeNotification object:self];
//
//    [defaultCenter addObserver:self selector:@selector(moviePlayerLoadStateDidChange:) name:IJKMPMoviePlayerLoadStateDidChangeNotification object:self];
//    [defaultCenter addObserver:self selector:@selector(moviePlayerPlaybackStateDidChange:) name:IJKMPMoviePlayerPlaybackStateDidChangeNotification object:self];
//    [defaultCenter addObserver:self selector:@selector(moviePlayerPlaybackDidFinish:) name:IJKMPMoviePlayerPlaybackDidFinishNotification object:self];
//
//    [defaultCenter addObserver:self selector:@selector(moviePlayerVideoDecoderOpen:) name:IJKMPMoviePlayerVideoDecoderOpenNotification object:self];
//    //[defaultCenter addObserver:self selector:@selector(moviePlayerFirstVideoFrameRendered:) name:IJKMPMoviePlayerFirstVideoFrameRenderedNotification object:self];
//    //[defaultCenter addObserver:self selector:@selector(moviePlayerFirstAudioFrameRendered:) name:IJKMPMoviePlayerFirstAudioFrameRenderedNotification object:self];
//
//    // link mic
//    [defaultCenter addObserver:self selector:@selector(linkMicDidJoinNotification) name:PLVLiveLinkMicDidJoinNotification object:nil];
//    [defaultCenter addObserver:self selector:@selector(linkMicDidLeaveNotification) name:PLVLiveLinkMicDidLeaveNotification object:nil];
//}

#pragma mark 直播播放器直播状态回调----
- (void)livePlayerPlaystateCallback{
    // 播放器的状态 - 非直播流状态
//    DLog(@"执行方法 %s",__FUNCTION__);
//    BOOL isPlay = _livePlayer.isPlaying;
//    DLog(@"执行方法 %@",isPlay?@"正在播放":@"暂无播放");
}
// 直播播断流后重新连接时创建一个新的播放器
- (void)livePlayerReconnectNotification:(NSNotification *)notification {
    // 接收到直播流后,自动播放
    DLog(@"执行方法 %s",__FUNCTION__);
    [self isRegistedPLVLive];
}
- (void)livePlayerWillChangeToFullScreenNotification {
    NSLog(@"将要全屏啦");
}
- (void)livePlayerWillExitFullScreenNotification {
    NSLog(@"将要退出全屏啦");
}
- (void)moviePlayerPlaybackStateDidChange:(NSNotification *)notification {
    if (_livePlayer.playbackState==IJKMPMoviePlaybackStatePlaying) {
        DLog("开始播放");
    }else if (_livePlayer.playbackState==IJKMPMoviePlaybackStateStopped || _livePlayer.playbackState==IJKMPMoviePlaybackStatePaused) {
        DLog("暂停/停止播放");
    }
}
- (void)moviePlayerPlaybackDidFinish:(NSNotification *)notification {
    DLog(@"流结束了?")
}

- (NSString *)getNowTimeTimestamp{
    NSDate *datenow = [NSDate date];//现在时间,你可以输出来看下是什么格式
    NSString *timeSp = [NSString stringWithFormat:@"%ld", (long)([datenow timeIntervalSince1970]*1000)];
    return timeSp;
}

-(UIView *)view{
    return _displayView;
}

-(void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result{
    if([[call method] isEqualToString:@"setVideoURI"]) {
        [self onSetVideoURI:call result:result];
    }else if([[call method] isEqualToString:@"brightness"]) { // 获取亮度
        result([self onBrightness]);
    }else if([[call method] isEqualToString:@"start"]) {
        [self onStart:call result:result];
    }else if([[call method] isEqualToString:@"pause"]) {
        [self onPause:call result:result];
    }else if ([[call method] isEqualToString:@"resume"]) {
        [self onResume:call result:result];
    }else if([[call method] isEqualToString:@"stop"]) {
        [self onStop:call result:result];
    }else if([[call method] isEqualToString:@"setLivePlay"]) {
        [self onSetLivePlay:call result:result];
    }else if([[call method] isEqualToString:@"isPlaying"]) {
        [_livePlayer isPlaying] ? result(@YES):result(@NO);
    }else if([[call method] isEqualToString:@"destroy"]) {
        [self onDestroy:call result:result];
//    }else if([[call method] isEqualToString:@"duration"]) {
//        result(@0);
//    }else if([[call method] isEqualToString:@"currentPosition"]) {
//        result(@0);
//    }else if([[call method] isEqualToString:@"bufferPercentage"]) {
//        result(@10);
    }else if([[call method] isEqualToString:@"volume"]) { // 获取音量
        result([self onGetVolume]);
    }else if([[call method] isEqualToString:@"setBrightness"]) { // 设置亮度
        [self onSetBrightness:call result:result];
    }else if([[call method] isEqualToString:@"setVolume"]) { // 设置音量
        [self onSetVolume:call result:result];
//    }else if([[call method] isEqualToString:@"initDanMu"]) {
        
    }else if([[call method] isEqualToString:@"sendDanMu"]) {
        [self onSendDanMu:call result:result];
    }else if([[call method] isEqualToString:@"initDanMu"]) {
        NSDictionary *argsMap = call.arguments;
//        NSString *padding = argsMap[@"padding"];
//        NSString *textSize = argsMap[@"textSize"];
//        NSString *textColor = argsMap[@"textColor"];
        result(nil);
    }else if([[call method] isEqualToString:@"showDanMu"]) {
        _danmuLayer.hidden = NO;
        _danmuEnable = YES;
    }else if([[call method] isEqualToString:@"hideDanMu"]) {
        _danmuEnable = NO;
        _danmuLayer.hidden = YES;
    }else if([[call method] isEqualToString:@"setOnChatListener"]) {
//        NSDictionary *dict = @{
////            @"type":@"doubleClick",
//        };
//        [self->_channel invokeMethod:@"chatListener" arguments:dict];
        result(nil);
    }else if([[call method] isEqualToString:@"getChatHistory"]) {
        NSDictionary *argsMap = call.arguments;
//        NSString *userId = argsMap[@"userId"];
        NSUInteger channelId = [argsMap[@"channelId"] intValue];
        NSUInteger begin = [argsMap[@"begin"] intValue];
        NSUInteger end = [argsMap[@"end"] intValue];
        if (!channelId) return;
        [PLVLiveAPI requestChatRoomHistoryWithRoomId:channelId startIndex:begin endIndex:end completion:^(NSArray *historyList) {
            [[PLVLiveManager sharedLiveManager] handleChatRoomHistoryMessage:historyList];
            NSArray *arr = [NSArray arrayWithArray:historyList];
            NSDictionary *dic = @{
                @"status":@"success",
                @"data":arr,
            };
            result(dic);
        } failure:^(PLVLiveErrorCode errorCode, NSString *description) {
            NSDictionary *dic = @{
                @"status":@"fail",
                @"msg":description,
                @"code":@"-10010",
            };
            result(dic);
        }];
    }else if([[call method] isEqualToString:@"getChatRoomListUsers"]) {
        NSDictionary *argsMap = call.arguments;
//        NSString *userId = argsMap[@"userId"];
        NSUInteger channelId = [argsMap[@"channelId"] intValue];
        NSUInteger page = [argsMap[@"page"] intValue];
        NSUInteger length = [argsMap[@"length"] intValue];
        if (!channelId) return;
        [PLVLiveAPI requestChatRoomListUsersWithRoomId:channelId page:page length:length completion:^(NSDictionary *listUsers) {
            NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:listUsers];
            NSDictionary *tmpDic = @{
                @"status":@"success",
            };
            [dic addEntriesFromDictionary:tmpDic];
            result(dic);
        } failure:^(PLVLiveErrorCode errorCode, NSString *description) {
            NSDictionary *dic = @{
                @"status":@"fail",
                @"msg":description,
                @"code":@"-10010",
            };
            result(dic);
        }];
    }else if([[call method] isEqualToString:@"sendChatMsg"]) {
        NSDictionary *argsMap = call.arguments;
        NSString *message = argsMap[@"message"];
        NSString *courseId = argsMap[@"courseId"];
        NSString *chapterId = argsMap[@"chapterId"];
        [self sendMsgWithMessage:message courseId:courseId chapterId:chapterId];
        result(nil);
    }else if([[call method] isEqualToString:@"initSocket"]) {
        NSDictionary *argsMap = call.arguments;
        NSString *channelId = argsMap[@"channelId"];
        NSString *nickName = argsMap[@"nickName"];
        NSString *avatar = argsMap[@"avatar"];
        if ([@"" isEqualToString:channelId]) channelId = @"127889";
        if ([@"" isEqualToString:nickName]) nickName = @"手机用户";
        if ([@"" isEqualToString:avatar]) avatar = @"https://www.polyv.net/images/effect/effect-device.png";
        [self initSocketIOWithChannelId:channelId nickName:nickName avatar:avatar];
        result(nil);
    }else{
        //其他方法的回调
        result(FlutterMethodNotImplemented);
    }
}

- (void)dealloc{
    [self dealloc_M];
}

- (void)dealloc_M{
    DLog(@"♻️ 通知释放");
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)onSetVideoURI:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSString *url = (NSString *)call.arguments;
    NSLog(@"传入播放地址 %@",url);
    result(nil);
}
- (void)onStart:(FlutterMethodCall*)call result:(FlutterResult)result {
    [_livePlayer isPlaying] ? : [_livePlayer play];
    result(nil);
}
- (void)onPause:(FlutterMethodCall*)call result:(FlutterResult)result {
    [_livePlayer isPlaying] ? [_livePlayer pause] : nil;
    result(nil);
}
- (void)onResume:(FlutterMethodCall*)call result:(FlutterResult)result {
    if ([_livePlayer isPlaying]) {
        NSLog(@"正在播放,点击继续无效!");
    }else{
        [_livePlayer stop];
        [self loadPlayer];
    }
    result(nil);
}
- (void)onStop:(FlutterMethodCall*)call result:(FlutterResult)result {
    [_livePlayer stop];
    result(nil);
}
- (void)onSetLivePlay:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSDictionary *argsMap = call.arguments;
    _userId = argsMap[@"userId"];
    _channelId = [argsMap[@"channelId"] intValue];
    if ([_userId isEqualToString:@""] || !_channelId) return;
    [self isRegistedPLVLive];
}
- (void)onDestroy:(FlutterMethodCall*)call result:(FlutterResult)result {
    [_livePlayer clearPlayer];
    _livePlayer = nil;
    [self closeSocketIO];
    [self dealloc_M];
}
- (NSNumber *)onBrightness {
    float tmp = [UIScreen mainScreen].brightness * 100;
    int a = (int)lroundf(tmp);
//    DLog(@"[LiveView打印2] 当前亮度>>>>> %d",a);
    return [NSNumber numberWithInt:a];
}
- (void)onSetBrightness:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSDictionary *argsMap = call.arguments;
    int brightness = [argsMap[@"brightness"] intValue];
    float tmp = brightness / 100.0;
//    DLog(@"[LiveView打印] 亮度settings >>>>> %f",tmp);
    [[UIScreen mainScreen] setBrightness:tmp];
}
- (NSNumber *)onGetVolume {
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    float tmp = audioSession.outputVolume * 100;
    int a = (int)lroundf(tmp);
    DLog(@"[LiveView打印] 当前音量>>>>> %d",a);
    return [NSNumber numberWithInt:a];
}
- (void)onSetVolume:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSDictionary *argsMap = call.arguments;
    int volumeValue = [argsMap[@"volume"] intValue];
    if (volumeValue > 100) volumeValue = 100;
    if (volumeValue < 0) volumeValue = 0;
    float tmp = volumeValue / 100.0;
    DLog(@"[LiveView打印] 音量settings >>>>> %f",tmp);
    [self.volumeSliderPlug setValue:tmp animated:NO];
}
- (void)onSendDanMu:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSDictionary *argsMap = call.arguments;
    NSString *msg = argsMap[@"message"];
    [self insertDanMuWithMsg:msg];
}

// 获取直播频道信息
- (void)isRegistedPLVLive{
    DLog("%@, %ld",_userId, (long)_channelId);
    __weak typeof(self)ws = self;
    [PLVLiveAPI loadChannelInfoRepeatedlyWithUserId:_userId channelId:_channelId completion:^(PLVLiveChannel *channel) {
        [channel updateChannelRestrictInfo:^(PLVLiveChannel *channel) {
            self->_liveChannel = channel;
            if (channel != nil) {
                [ws loadPlayer];
            }else{
                DLog(@">>>>>> liveChannel model为空!");
            }
        }];
    } failure:^(PLVLiveErrorCode errorCode, NSString *description) {
        DLog(@">>>>>> 获取liveChannel 失败!");
        // 不可保利威直播
        self->_liveChannel = nil;
    }];
}

- (void)loadPlayer {
    _livePlayer = [self initializeLivePlayer];
    _stream = _liveChannel.stream;
    _danmuEnable = NO;
    // 根据频道号获取当前流状态（是否直播中及直播模式）
    __weak typeof(self) weakSelf = self;
    [PLVLiveAPI getStreamStatusWithChannelId:_channelId stream:_stream completion:^(PLVLiveStreamState streamState, NSString *mode) {
        if (streamState == PLVLiveStreamStateNoStream) {
            DLog(@"当前暂无直播")
            __strong typeof(weakSelf) strongSelf = weakSelf;
            NSDictionary *dict = @{
                @"type":@"streamState",
                @"state":@"NoStream",
            };
            [strongSelf->_channel invokeMethod:@"listener" arguments:dict];
        }else {
            [self->_livePlayer play];
        }
    } failure:^(PLVLiveErrorCode errorCode, NSString *description) {
        [self->_livePlayer play];
    }];
}

- (PLVLivePlayerController *)initializeLivePlayer {
    _livePlayer = nil;
    if (!_livePlayer) {
        _livePlayer = [[PLVLivePlayerController alloc] initWithChannel:_liveChannel displayView:_displayView];
        [IJKFFMoviePlayerController setLogLevel:k_IJK_LOG_INFO];    // 日志等级
        [self configCallBackBlock];
        [_livePlayer insertDanmuView:self.danmuLayer]; // 添加弹幕层
        return _livePlayer;
    }else{
        return _livePlayer;
    }
}

- (void)configCallBackBlock {
    __weak typeof(self)weakSelf = self;
    [_livePlayer setReturnButtonClickBlock:^{
        NSLog(@"返回按钮点击了...");
        __strong typeof(weakSelf) strongSelf = weakSelf;
        NSDictionary *dict = @{
            @"type":@"back",
        };
        [strongSelf->_channel invokeMethod:@"listener" arguments:dict];
    }];
    [_livePlayer setPlayButtonClickBlock:^{
        NSLog(@"播放按钮点击了...");
    }];
    [_livePlayer setPauseButtonClickBlock:^{
        NSLog(@"暂停按钮点击了...");
    }];
    [_livePlayer setFullScreenButtonClickBlock:^{
        NSLog(@"全屏按钮点击了...");
    }];
    [_livePlayer setSmallScreenButtonClickBlock:^{
        NSLog(@"小屏按钮点击了...");
    }];
    [_livePlayer setCoverImageBeClickedBlock:^(NSString *coverHref) {
        NSLog(@"点击了暖场图片，链接：%@",coverHref);
    }];
    [_livePlayer setDanmuEnableCallBack:^(BOOL danmuEnable) {
        NSLog(@"弹幕开启：%d",danmuEnable);
        self->_danmuEnable = danmuEnable;
    }];
    [_livePlayer setSingleTapClickBlock:^{
        NSLog(@"单击事件...");
        __strong typeof(weakSelf) strongSelf = weakSelf;
        NSDictionary *dict = @{
            @"type":@"click",
        };
        [strongSelf->_channel invokeMethod:@"listener" arguments:dict];
    }];
    [_livePlayer setDoubleClickBlock:^{
        NSLog(@"双击事件...");
        __strong typeof(weakSelf) strongSelf = weakSelf;
        NSDictionary *dict = @{
            @"type":@"doubleClick",
        };
        [strongSelf->_channel invokeMethod:@"listener" arguments:dict];
    }];
    [_livePlayer setLeftUpClickBlock:^{
        NSLog(@"左侧上滑事件...");
//        int i = [self onBrightness];
//        DLog(@"%d",i);
        __strong typeof(weakSelf) strongSelf = weakSelf;
        NSDictionary *dict = @{
            @"type":@"leftUp",
        };
        [strongSelf->_channel invokeMethod:@"listener" arguments:dict];
    }];
    [_livePlayer setLeftDownClickBlock:^{
        NSLog(@"左侧下滑事件...");
        __strong typeof(weakSelf) strongSelf = weakSelf;
        NSDictionary *dict = @{
            @"type":@"leftDown",
        };
        [strongSelf->_channel invokeMethod:@"listener" arguments:dict];
    }];
    [_livePlayer setRightUpClickBlock:^{
        NSLog(@"右侧上滑事件...");
//        int i = [self onVolume];
//        DLog(@"%d",i);
        __strong typeof(weakSelf) strongSelf = weakSelf;
        NSDictionary *dict = @{
            @"type":@"rightUp",
        };
        [strongSelf->_channel invokeMethod:@"listener" arguments:dict];
    }];
    [_livePlayer setRightDownClickBlock:^{
        NSLog(@"右侧下滑事件...");
        __strong typeof(weakSelf) strongSelf = weakSelf;
        NSDictionary *dict = @{
            @"type":@"rightDown",
        };
        [strongSelf->_channel invokeMethod:@"listener" arguments:dict];
    }];
    [_livePlayer setLiveStateChangedBlock:^{
        // 貌似只有接收到直播源好用, 直播源结束没反应
//        __strong typeof(weakSelf) strongSelf = weakSelf;
        DLog(@"直播源状态改变了");
    }];
}

- (void)insertDanMuWithMsg:(NSString *)msg{
    NSString * message = @"我是一只小跳蛙";
    if (![@"" isEqualToString:msg]) message = msg;
    if (message && _danmuEnable) {
        [_danmuLayer insertDML:message];    // 插入弹幕信息
    }
}

#pragma mark - Lazy Load

- (ZJZDanMu *)danmuLayer {
    if (!_danmuLayer) {
        _danmuLayer = [[ZJZDanMu alloc] initWithFrame:CGRectMake(0, 20, CGRectGetWidth(_displayView.bounds), CGRectGetHeight(_displayView.bounds) -20)];
    }
    return _danmuLayer;
}

- (void)initSocketIOWithChannelId:(NSString *)channelId nickName:(NSString *)nickName avatar:(NSString *)avatar {
    __weak typeof(self)weakSelf = self;
    DLog(@"initSocketIO:::\n appId = %@ \n appSecret = %@",_appId,_appSecret);
    [PLVLiveAPI requestAuthorizationForLinkingSocketWithChannelId:_channelId Appld:_appId appSecret:_appSecret success:^(NSDictionary *responseDict) {
        __strong typeof (weakSelf)strongSelf = weakSelf;
        // 1.初始化 socketIO 连接对象
        strongSelf->_socketIO = [[PLVSocketIO alloc] initSocketIOWithConnectToken:responseDict[@"chat_token"] enableLog:NO];
        strongSelf->_socketIO.delegate = weakSelf;
        [strongSelf->_socketIO connect];
        //weakSelf.socketIO.debugMode = YES;
        
        // 2.初始化一个socket登录对象（昵称和头像使用默认设置）
        strongSelf -> _nickName = nickName;
        strongSelf -> _avatar = avatar;
        strongSelf -> _channelId = channelId.intValue;
        strongSelf->_login = [PLVSocketObject socketObjectForLoginEventWithRoomId:strongSelf->_channelId nickName:strongSelf->_nickName avatar:strongSelf->_avatar userType:PLVSocketObjectUserTypeStudent];
        //NSDictionary *authorization = @{@"actor":@"自定义头衔",@"bgColor":@"#000000",@"fColor":@"#ffffff"};
        //self.login = [PLVSocketObject socketObjectForLoginEventWithRoomId:self.channelId nickName:self.nickName avatar:self.avatar userId:nil authorization:authorization];
        
        // 3.数据存储
        PLVLiveManager *manager = [PLVLiveManager sharedLiveManager];
        manager.login = strongSelf->_login;
        manager.linkMicParams = responseDict;
    } failure:^(PLVLiveErrorCode errorCode, NSString *description) {
        [PLVUtils showHUDWithTitle:@"聊天室连接失败！" detail:[NSString stringWithFormat:@"错误码:%ld, 信息:%@",(long)errorCode,description] view:self->_displayView];
    }];
}

- (void)closeSocketIO{
    [_socketIO disconnect];
    [_socketIO removeAllHandlers];
    _socketIO.delegate = nil;
    _socketIO = nil;
}

#pragma mark - Private methods

- (void)showNoPermissionAlert {
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:_displayView animated:YES];
    hud.mode = MBProgressHUDModeText;
//    hud.label.text = title;
    hud.detailsLabel.text = @"您未被授权观看本直播";
    [hud hideAnimated:YES afterDelay:1.0];
}

- (int)emitSocketIOMessage:(PLVSocketObject *)socketObject {
    if (_socketIO) {
        //NSLog(@"socketIOState:%ld",self.socketIO.socketIOState);
        if (_loginSuccess && _socketIO.socketIOState == PLVSocketIOStateConnected) {
            [_socketIO emitMessageWithSocketObject:socketObject];
            return 1;
        }else {
            [PLVUtils showHUDWithTitle:@"消息发送失败！" detail:[NSString stringWithFormat:@"登录失败或连接失败，state:%ld",(long)_socketIO.socketIOState] view:_displayView];
            return 0;
        }
    }else {
        NSLog(@"socket.io not init.");
        return 0;
    }
}

#pragma mark - <PLVSocketIODelegate>
/// 连接成功
- (void)socketIO:(PLVSocketIO *)socketIO didConnectWithInfo:(NSString *)info {
    DLog(@"%@--%@",NSStringFromSelector(_cmd),info);
    [_socketIO emitMessageWithSocketObject:_login];       // 登录聊天室
}

/// 收到聊天室信息
- (void)socketIO:(PLVSocketIO *)socketIO didReceiveChatMessage:(PLVSocketChatRoomObject *)chatObject {
    DLog(@"%@--type:%lu, event:%@",NSStringFromSelector(_cmd),(unsigned long)chatObject.eventType,chatObject.event);
//    [_chatroomController addNewChatroomObject:chatObject];
    
    __weak typeof(self)weakSelf = self;
    NSString *message = [[PLVLiveManager sharedLiveManager] handleChatroomObject:chatObject completion:^(BOOL isChatroom) {
//        __strong typeof (weakSelf)strongSelf = weakSelf;
//        if (isChatroom) {
//            [strongSelf->_chatroomController updateChatroom];
//        }else {
//            if (strongSelf->_privateChatController) {
//                [strongSelf->_privateChatController updateChatroom];
//            }
//        }
    }];
    
    /**
     * 1. 自己进入也会走LOGIN
     * 2. ADD_SHIELD和REMOVE_SHIELD代表禁言的是自己
     * 3. 聊天室的全体禁言的打开和关闭都是CLOSEROOM
     */
    if (chatObject.eventType == PLVSocketChatRoomEventType_SPEAK || chatObject.eventType == PLVSocketChatRoomEventType_ADD_SHIELD || chatObject.eventType == PLVSocketChatRoomEventType_REMOVE_SHIELD || chatObject.eventType == PLVSocketChatRoomEventType_KICK || chatObject.eventType == PLVSocketChatRoomEventType_CLOSEROOM) {
//        PLVLiveManager *liveManager = [PLVLiveManager sharedLiveManager];
//        PLVSocketChatRoomObject *mySpeak = [PLVSocketChatRoomObject chatRoomObjectForSpeakEventTypeWithRoomId:liveManager.login.roomId content:message];
        
        NSDictionary *user = chatObject.jsonDict[PLVSocketIOChatRoom_SPEAK_userKey];
//        NSDictionary *time = chatObject.jsonDict[PLVSocketIOChatRoom_SPEAK_time];
        NSString *status = chatObject.jsonDict[@"status"];
        NSString *nickname = chatObject.jsonDict[PLVSocketIOChatRoom_LOGIN_userKey][PLVSocketIOChatRoomUserNickKey];
        NSString *nickpic = chatObject.jsonDict[PLVSocketIOChatRoom_LOGIN_userKey][PLVSocketIOChatRoomUserPicKey];
//        [self.chatroomObjects addObject:[NSString stringWithFormat:@"欢迎%@加入",nickname]];
//        DLog(@"监听到的消息对象 >>>> %@",chatObject.jsonDict);
        
//        if (status) {
//            if ([status isEqualToString:@"censor"]) { // 聊天室审核
//            }else if ([status isEqualToString:@"error"]) { // 严禁词
//            }
//        }else if (user) {
//            NSString *userId = [NSString stringWithFormat:@"%@",user[PLVSocketIOChatRoomUserUserIdKey]];
//            if ([userId isEqualToString:self.login.userId]) {
//                break;
//            }
//            [self.chatroomObjects addObject:chatroomObject];
//            completion(YES);
//            return [chatroomObject.jsonDict[PLVSocketIOChatRoom_SPEAK_values] firstObject];
//        }
        NSDictionary *dict = @{
            @"type":@"receive_message",
            @"data":!chatObject.jsonDict?@"":chatObject.jsonDict,
        };
        [_channel invokeMethod:@"chatListener" arguments:dict];
    }
    
    if (chatObject.eventType == PLVSocketChatRoomEventType_LOGIN
        || chatObject.eventType == PLVSocketChatRoomEventType_LOGOUT) {
        NSDictionary *dict = @{
            @"type":@"login_logout",
            @"data":!chatObject.jsonDict?@"":chatObject.jsonDict,
        };
        [_channel invokeMethod:@"chatListener" arguments:dict];
    }
    if (message && _danmuEnable) {
        [_danmuLayer insertDML:message];    // 插入弹幕信息
    }
    
    if (chatObject.eventType == PLVSocketChatRoomEventType_LOGIN
        || chatObject.eventType == PLVSocketChatRoomEventType_LOGOUT) {
        _loginSuccess = YES;
    }
}

/// 收到连麦消息
- (void)socketIO:(PLVSocketIO *)socketIO didReceiveLinkMicMessage:(PLVSocketLinkMicObject *)linkMicObject {
    DLog(@"%@--type:%lu, event:%@",NSStringFromSelector(_cmd),(unsigned long)linkMicObject.eventType,linkMicObject.event);
    _onlineListController.linkMicObject = linkMicObject;
}

/// 失去连接
- (void)socketIO:(PLVSocketIO *)socketIO didDisconnectWithInfo:(NSString *)info {
    DLog(@"%@--%@",NSStringFromSelector(_cmd),info);
    _loginSuccess = NO;
}

/// 连接出错
- (void)socketIO:(PLVSocketIO *)socketIO connectOnErrorWithInfo:(NSString *)info {
    DLog(@"%@--%@",NSStringFromSelector(_cmd),info);
}

/// 重连SocketIO服务器
- (void)socketIO:(PLVSocketIO *)socketIO reconnectWithInfo:(NSString *)info {
    DLog(@"%@--%@",NSStringFromSelector(_cmd),info);
}

/// 本地错误信息
- (void)socketIO:(PLVSocketIO *)socketIO localError:(NSString *)description {
    DLog(@"%@--%@",NSStringFromSelector(_cmd),description);
}

#pragma mark - <PLVChatroomDelegate>

- (void)chatroom:(PLVChatroomController *)chatroom didOpenError:(PLVChatroomErrorCode)code {
    if (code==PLVChatroomErrorCodeBeKicked) {
        [self showNoPermissionAlert];
    }
}

- (void)emitChatroomObject:(PLVSocketChatRoomObject *)chatRoomObject withMessage:(NSString *)message {
    int code = [self emitSocketIOMessage:chatRoomObject];
    if (code && message && _danmuEnable) {
        [_danmuLayer insertDML:message];
    }
}

#pragma mark - <PLVOnlineListDelegate>

- (void)emitLinkMicObject:(PLVSocketLinkMicObject *)linkMicObject {
    [self emitSocketIOMessage:linkMicObject];
}

// 发送聊天内容
- (void)sendMsgWithMessage:(NSString *)sendText courseId:(NSString *)courseId chapterId:(NSString *)chapterId {
    sendText = [sendText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    NSString *temp = [sendText stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    sendText = [temp stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    PLVLiveManager *liveManager = [PLVLiveManager sharedLiveManager];
    PLVSocketChatRoomObject *mySpeak = [PLVSocketChatRoomObject chatRoomObjectForSpeakEventTypeWithRoomId:liveManager.login.roomId content:sendText];
    NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:mySpeak.jsonDict]  ;
    NSMutableDictionary *sessionIdDic = [[NSMutableDictionary alloc]init];
        sessionIdDic[@"courseId"] = courseId.length>0?courseId:@"";
        sessionIdDic[@"curriculumId"] = chapterId.length>0?chapterId:@"";
    [dic setObject:sessionIdDic forKey:@"sessionId"];
    NSMutableDictionary *userDic = [[NSMutableDictionary alloc]init];
    userDic[@"banned"] = false;
    userDic[@"channelId"] = [NSString stringWithFormat:@"%lu",(unsigned long)_channelId];
    userDic[@"clientIp"] = @"";
    userDic[@"uid"] = @"";
    userDic[@"userType"] = @"";
    userDic[@"nick"] = !_nickName?@"":_nickName;
    userDic[@"pic"] = !_avatar?@"":_avatar;
    userDic[@"roomId"] = @"";
    userDic[@"userId"] = @"";
    userDic[@"actor"] = @"";
    userDic[@"sessionId"] = @"";
    userDic[@"userSource"] = @"";
    [dic setObject:@"" forKey:@"id"];
    [dic setObject:[self getNowTimeTimestamp] forKey:@"time"];
    [dic setObject:userDic forKey:@"user"];
    
    mySpeak.jsonDict = dic;
    mySpeak.localMessage = YES;
    if (sendText.length>0) {
        NSDictionary *dict = @{
            @"type":@"receive_message",
            @"data":!mySpeak.jsonDict?@"":mySpeak.jsonDict,
        };
        [_channel invokeMethod:@"chatListener" arguments:dict];
        
        [self emitChatroomObject:mySpeak withMessage:sendText];
        
//        dispatch_async(dispatch_get_main_queue(), ^{
//            // 此处刷新聊天列表
//        });
//        dispatch_async(dispatch_get_main_queue(), ^{
//            if([PLVLiveManager sharedLiveManager].chatroomObjects.count> 0){
//                // 此处滚动聊天列表
////                    NSIndexPath *indexpath = [NSIndexPath indexPathForRow:([PLVLiveManager sharedLiveManager].chatroomObjects.count-1) inSection:0];
////                    [self.liveView.tableView scrollToRowAtIndexPath:indexpath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
//            }
//        });
    }else{
        DLog(@"发送消息不能为空");
    }
}

@end
